home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /**
- Parse predicates, building a parse tree in the process.
- Uses recursive descent parsing, because it's so easy to write
- **/
-
- #include <stdio.h>
- #include "attribute.h"
- #include "digraph.h"
- #include "token.h"
- #include "pparse.h"
-
- BOOL token_read;
- BOOL error;
- TOKEN current;
- int lineno;
-
- extern char string_val[MAXBUFFER];
-
- TOKEN get_token();
- TOKEN get_next_token();
- PTREE *get_ifstmt(), *get_setstmt(), *get_displaystmt(), *get_hidestmt();
- PTREE *get_focusstmt(), *get_coalescestmt(), *get_expandstmt();
- PTREE *get_breakstmt(), *get_continuestmt();
- PTREE *get_bexpr(), *get_bterm(), *get_bfactor();
- PTREE *get_node(), *get_nodel(), *get_attr(), *get_rval(), *get_rest_of_attr();
- PTREE *get_fnodel(), *get_rest_of_node(), *get_attr_name();
- PTREE *get_command(), *get_command_list(), *get_commands();
-
- init_parse(pfile)
- FILE *pfile;
- {
- init_reader(pfile);
- lineno = 1;
- error = FALSE;
- token_read = FALSE;
- }
-
- gobble_token()
- {
- (void) get_token(TRUE, TRUE);
- }
-
- TOKEN get_token(reserved, str_restricted)
- BOOL reserved, str_restricted;
- /**
- Get the next token. Used along with lookahead (below) to implement
- lookahead painlessly
- **/
- {
- if (token_read)
- {
- token_read = FALSE;
- }
- else
- {
- while((current = get_next_token(reserved, str_restricted)) ==
- NEWLINE_TOKEN)
- /* ignore newlines, except to keep track of the line number */
- {
- lineno++;
- }
- }
-
- return current;
- }
-
- TOKEN lookahead(reserved, str_restricted)
- BOOL reserved, str_restricted;
- /* return the next 'unread' token */
- {
- if (!token_read)
- {
- token_read = TRUE;
- while((current = get_next_token(reserved, str_restricted)) ==
- NEWLINE_TOKEN)
- {
- lineno++;
- }
- }
-
- return current;
- }
-
- BOOL match_token(t, reserved, str_restricted)
- TOKEN t;
- BOOL reserved, str_restricted;
- /**
- Check that the next token is t, if not, print an error message
- **/
- {
- TOKEN s;
-
- if ((s = get_token(reserved, str_restricted)) == t)
- {
- return TRUE;
- }
- else
- {
- print_lineno();
- fprintf (stderr, "Expecting token ");
- print_token(t, FALSE);
- /**
- the preceding will look stupid if the token is STRING_TOKEN,
- for example, because print_token will print the current
- string_val.
- **/
- fprintf (stderr, " got ");
- print_token(s, TRUE);
- error = TRUE;
- return FALSE;
- }
- }
-
- PTREE *get_command ()
- /**
- get a command
-
- COMMAND -> HIDESTMT | IFSTMT | SETSTMT | COALESCESTMT | EXPANDSTMT |
- DISPLAYSTMT | FOCUSSTMT | BREAKSTMT | CONTINUESTMT |
- ;
- **/
- {
- TOKEN t;
-
- ck;
-
- t = get_token(TRUE, TRUE);
-
- switch (t)
- {
- case EOF_TOKEN:
- return NULL;
- case SEMICOLON_TOKEN:
- return NULL;
- case IF_TOKEN:
- return get_ifstmt();
- case SET_TOKEN:
- return get_setstmt();
- case COALESCE_TOKEN:
- return get_coalescestmt();
- case EXPAND_TOKEN:
- return get_expandstmt();
- case HIDE_TOKEN:
- return get_hidestmt();
- case DISPLAY_TOKEN:
- return get_displaystmt();
- case FOCUS_TOKEN:
- return get_focusstmt();
- case BREAK_TOKEN:
- return get_breakstmt();
- case CONTINUE_TOKEN:
- return get_continuestmt();
- default:
- print_lineno();
- fprintf (stderr, "parse error: token ");
- print_token(t, FALSE);
- fprintf (stderr, " cannot begin a statement\n");
- error = TRUE;
- return NULL;
- }
- }
-
- PTREE *get_hidestmt()
- /**
- HIDESTMT -> hide NODE ;
- **/
- {
- PTREE *left, *this;
- int tmp;
-
- ck;
- tmp = lineno;
-
- left = get_node();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = HIDE_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = left;
-
- return this;
- }
-
- PTREE *get_displaystmt()
- /**
- DISPLAYSTMT -> display NODE ;
- **/
- {
- PTREE *left, *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_node();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = DISPLAY_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = left;
-
- return this;
- }
-
- PTREE *get_focusstmt()
- /**
- FOCUSSTMT -> focus NODE ;
- **/
- {
- PTREE *left, *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_node();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = FOCUS_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = left;
-
- return this;
- }
-
- PTREE *get_expandstmt()
- /**
- EXPANDSTMT -> expand NODE ;
- **/
- {
- PTREE *left, *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_node();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = EXPAND_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = left;
-
- return this;
- }
-
- PTREE *get_breakstmt()
- /**
- BREAKSTMT -> break ;
- **/
- {
- PTREE *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = BREAK_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = NULL;
-
- return this;
- }
-
- PTREE *get_continuestmt()
- /**
- CONTINUESTMT -> continue ;
- **/
- {
- PTREE *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = CONTINUE_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = NULL;
-
- return this;
- }
-
- PTREE *get_coalescestmt()
- /**
- COALESCESTMT -> coalesce NODE NODE ;
- **/
- {
- PTREE *left, *right, *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_node();
- ck;
-
- right = get_node();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = COALESCE_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
-
- return this;
- }
-
- PTREE *get_ifstmt()
- /**
- 'if' or 'elsif' has already been read
-
- IFSTMT -> if BEXPR then COMMAND_LIST
- [elsif BEXPR then COMMAND_LIST ...]
- [else COMMAND_LIST]
- endif
- **/
- {
- PTREE *lleft, *rleft, *right, *this;
- TOKEN t;
- int tmp1, tmp2;
-
- ck;
-
- tmp1 = lineno;
- lleft = get_bexpr();
- ck;
-
- ck_match(THEN_TOKEN);
-
- tmp2 = lineno;
- rleft = get_command_list();
- ck;
-
- t = get_token(TRUE, TRUE);
-
- switch(t)
- {
- case ELSE_TOKEN:
- right = get_command_list();
- ck;
-
- ck_match(ENDIF_TOKEN);
- break;
- case ELSIF_TOKEN:
- right = get_ifstmt();
- ck;
-
- break;
- case ENDIF_TOKEN:
- right = NULL;
- break;
- default:
- print_lineno();
- fprintf(stderr,
- "Invalid token in if statement after statement list:");
- print_token(t, TRUE);
- error = TRUE;
- return NULL;
- }
-
- new(this, PTREE);
- this->token = IF_TOKEN;
- this->val = NULL;
- this->lineno = tmp1;
- this->right = right;
-
- new(this->left, PTREE);
- this->left->token = THEN_TOKEN;
- this->left->val = NULL;
- this->left->lineno = tmp2;
- this->left->right = rleft;
- this->left->left = lleft;
- return this;
- }
-
- PTREE *get_setstmt()
- /**
- SETSTMT -> set ATTR = RVAL ;
- **/
- {
- PTREE *left, *right, *this;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_attr();
- ck;
-
- ck_match(EQUAL_TOKEN);
-
- right = get_rval();
- ck;
-
- ck_match(SEMICOLON_TOKEN);
-
- new(this, PTREE);
- this->token = SET_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->left = left;
- this->right = right;
-
- return this;
- }
-
- PTREE *get_attr()
- /**
- ATTR -> fnodel . REST_OF_ATTR
- **/
- {
- PTREE *this, *left, *right;
- int tmp;
-
- ck;
-
- tmp = lineno;
- left = get_fnodel();
- ck;
-
- ck_match(PERIOD_TOKEN);
-
- right = get_rest_of_attr();
- ck;
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->left = left;
- this->right = right;
-
- return this;
- }
-
- PTREE *get_attr_name()
- /**
- ATTR_NAME -> STRING | brush | shape | color | displayed | coalescer |
- node | edge
- **/
- {
- PTREE *this;
- TOKEN t;
-
- ck;
-
- t = get_token(TRUE, TRUE);
-
- switch(t)
- {
- case STRING_TOKEN:
- new(this, PTREE);
- this->token = STRING_TOKEN;
- strsave(this->val, string_val);
- this->lineno = lineno;
- this->left = NULL;
- this->right = NULL;
- break;
- case BRUSH_TOKEN:
- case SHAPE_TOKEN:
- case COLOR_TOKEN:
- case DISPLAYED_TOKEN:
- case COALESCER_TOKEN:
- case NODE_TOKEN:
- case EDGE_TOKEN:
- new(this, PTREE);
- this->token = t;
- this->val = NULL;
- this->lineno = lineno;
- this->right = NULL;
- this->left = NULL;
- break;
- default:
- print_lineno();
- fprintf(stderr, "Attribute name cannot be ");
- print_token(t, TRUE);
- error = TRUE;
- return NULL;
- }
-
- return this;
- }
-
- PTREE *get_rest_of_attr()
- /**
- REST_OF_ATTR -> ATTR_NAME | NODEL . REST_OF_ATTR
- **/
- {
- PTREE *this, *left, *right;
- TOKEN t;
- int tmp;
-
- ck;
-
- t = lookahead(TRUE, TRUE);
-
- if (t == STRING_TOKEN)
- {
- left = get_nodel();
- ck;
-
- if (lookahead(TRUE, TRUE) == PERIOD_TOKEN)
- {
- gobble_token();
- tmp = lineno;
-
- right = get_rest_of_attr();
- ck;
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->left = left;
- this->right = right;
- }
- else
- {
- this = left;
- }
- }
- else if (attr_starter(t))
- {
- this = get_attr_name();
- ck;
- }
- else if (node_starter(t))
- {
- left = get_nodel();
- ck;
-
- ck_match(PERIOD_TOKEN);
-
- tmp = lineno;
- right = get_rest_of_attr();
- ck;
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->left = left;
- this->right = right;
- }
- else
- {
- print_lineno();
- fprintf(stderr, "Attribute designator cannot start with ");
- gobble_token();
- print_token(t, TRUE);
- error = TRUE;
- return NULL;
- }
-
- return this;
- }
-
- PTREE *get_node()
- /**
- NODE -> FNODEL . [REST_OF_NODE]
- **/
- {
- PTREE *this, *left, *right;
- TOKEN t;
- int tmp;
-
- ck;
-
- left = get_fnodel();
- ck;
-
- ck_match(PERIOD_TOKEN);
-
- tmp = lineno;
- t = lookahead(TRUE, TRUE);
-
- if (node_starter(t))
- {
- right = get_rest_of_node();
- ck;
- }
- else
- {
- right = NULL;
- }
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
- return this;
- }
-
- PTREE *get_rest_of_node()
- /**
- REST_OF_NODE -> NODEL . [REST_OF_NODE]
- **/
- {
- PTREE *this, *left, *right;
- TOKEN t;
- int tmp;
-
- ck;
-
- left = get_nodel();
- ck;
-
- ck_match(PERIOD_TOKEN);
-
- tmp = lineno;
- t = lookahead(TRUE, TRUE);
-
- if (node_starter(t))
- {
- right = get_rest_of_node();
- ck;
- }
- else
- {
- right = NULL;
- }
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
- return this;
- }
-
- PTREE *get_fnodel()
- /**
- first field of a node/edge designator
-
- FNODEL -> QSTRING | e e = empty string
- **/
- {
- PTREE *this;
- TOKEN t;
-
- ck;
-
- t = lookahead(TRUE, TRUE);
-
- switch(t)
- {
- case PERIOD_TOKEN:
- this = NULL;
- break;
- case QSTRING_TOKEN:
- gobble_token();
-
- new(this, PTREE);
- this->token = t;
- strsave(this->val, string_val);
- this->lineno = lineno;
- this->right = NULL;
- this->left = NULL;
- break;
- default:
- gobble_token();
- print_lineno();
- fprintf(stderr, "Node/edge designator cannot start with ");
- print_token(t, TRUE);
- error = TRUE;
- return NULL;
- }
-
- return this;
- }
-
- PTREE *get_nodel()
- /**
- NODEL -> STRING | in | out | source | sink | parents | children |
- ancestors | descendants
- **/
- {
- PTREE *this;
- TOKEN t;
-
- ck;
-
- t = get_token(TRUE, TRUE);
-
- switch(t)
- {
- case STRING_TOKEN:
- new(this, PTREE);
- this->token = t;
- strsave(this->val, string_val);
- this->lineno = lineno;
- this->right = NULL;
- this->left = NULL;
- break;
- case IN_TOKEN:
- case OUT_TOKEN:
- case SOURCE_TOKEN:
- case SINK_TOKEN:
- case PARENTS_TOKEN:
- case CHILDREN_TOKEN:
- case ANCESTORS_TOKEN:
- case DESCENDANTS_TOKEN:
- new(this, PTREE);
- this->token = t;
- this->val = NULL;
- this->lineno = lineno;
- this->right = NULL;
- this->left = NULL;
- break;
- default:
- print_lineno();
- fprintf(stderr, "Node/edge designator cannot start with ");
- print_token(t, TRUE);
- error = TRUE;
- return NULL;
- }
-
- return this;
- }
-
- PTREE *get_rval()
- /**
- RVAL = ATTR | QSTRING
- **/
- {
- int tmp;
-
- ck;
-
- if (lookahead(TRUE, TRUE) == QSTRING_TOKEN)
- {
- PTREE *left;
-
- gobble_token();
- new(left, PTREE);
- left->token = QSTRING_TOKEN;
- strsave(left->val, string_val);
- left->lineno = lineno;
- left->right = left->left = NULL;
-
- if (lookahead(TRUE, TRUE) == PERIOD_TOKEN)
- {
- PTREE *right, *this;
-
- gobble_token();
- tmp = lineno;
- right = get_rest_of_attr();
- ck;
-
- new(this, PTREE);
- this->token = PERIOD_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->left = left;
- this->right = right;
- return this;
- }
- else
- {
- return left;
- }
- }
- else
- {
- return get_attr();
- }
- }
-
- /**
- The following 3 functions implement precedence and associativity
- rules for boolean expressions
- **/
-
- PTREE *get_bexpr()
- /**
- BEXPR -> BTERM | BTERM and BEXPR | BTERM or BEXPR
- **/
- {
- PTREE *this, *left;
- TOKEN t;
- int tmp;
-
- ck;
-
- left = get_bterm();
- ck;
-
- if ((t = lookahead(TRUE, TRUE)) == AND_TOKEN || t == OR_TOKEN)
- {
- PTREE *right;
-
- gobble_token();
- tmp = lineno;
- right = get_bexpr();
- ck;
-
- new(this, PTREE);
- this->token = t;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
- return this;
- }
- else
- {
- return left;
- }
- }
-
- PTREE *get_bterm()
- /**
- BTERM -> not BFACTOR | BFACTOR
- **/
- {
- PTREE *this, *left;
- int tmp;
-
- ck;
-
- if (lookahead(TRUE, TRUE) == NOT_TOKEN)
- {
- gobble_token();
- tmp = lineno;
- left = get_bfactor();
- ck;
-
- new(this, PTREE);
- this->token = NOT_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = NULL;
- this->left = left;
- return this;
- }
- else
- {
- return get_bfactor();
- }
- }
-
- PTREE *get_bfactor()
- /**
- BFACTOR -> ( BEXPR ) | RVAL | RVAL = RVAL
- **/
- {
- PTREE *this, *left, *right;
- int tmp;
-
- ck;
-
- if (lookahead(TRUE, TRUE) == OPENPAREN_TOKEN)
- {
- gobble_token();
- this = get_bexpr();
- ck;
-
- ck_match(CLOSEPAREN_TOKEN);
- }
- else
- {
- left = get_rval();
- ck;
-
- if (lookahead(TRUE, TRUE) == EQUAL_TOKEN)
- {
- gobble_token();
- tmp = lineno;
- right = get_rval();
- ck;
- }
- else
- {
- tmp = lineno;
- right = NULL;
- }
-
- new(this, PTREE);
- this->token = EQUAL_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
- }
-
- return this;
- }
-
- PTREE *get_command_list()
- /**
- COMMAND_LIST -> COMMAND [COMMAND_LIST]
- **/
- {
- PTREE *this, *left, *right;
- TOKEN t;
- int tmp;
-
- ck;
-
- t = lookahead(TRUE, TRUE);
-
- if (!command_list_ender(t))
- {
- tmp = lineno;
- left = get_command();
- ck;
-
- right = get_command_list();
- ck;
-
- new(this, PTREE);
- this->token = SEMICOLON_TOKEN;
- this->val = NULL;
- this->lineno = tmp;
- this->right = right;
- this->left = left;
-
- return this;
- }
- else
- {
- return NULL;
- }
- }
-
- PTREE *get_commands(err)
- BOOL *err;
- /**
- Get the commands (function to call from the top level)
- **/
- {
- PTREE *this;
- TOKEN t;
-
- this = get_command_list();
-
- if (error)
- {
- gobble_rest_of_tokens();
- *err = TRUE;
- return NULL;
- }
- else if ((t = lookahead(TRUE, TRUE)) != EOF_TOKEN)
- /* check the file didn't end prematurely */
- {
- print_lineno();
- fprintf(stderr, "Cannot end commands with ");
- print_token(t, TRUE);
- gobble_token();
- gobble_rest_of_tokens();
- *err = TRUE;
- return NULL;
- }
- else
- {
- err = FALSE;
- return this;
- }
- }
-
- gobble_rest_of_tokens()
- {
- while (get_token(TRUE, TRUE) != EOF_TOKEN)
- {
- }
- }
-
- print_lineno()
- {
- fprintf(stderr, "on line #%d: ", lineno);
- }
-